home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / asmutil / asm_n_z.zip / SPY.ASM < prev    next >
Assembly Source File  |  1987-05-11  |  16KB  |  386 lines

  1. name spy
  2.  
  3. rt        equ    0dh    ; return
  4. lf        equ    0ah    ; linefeed
  5. eof        equ    1ah    ; end of file
  6. ok_seg        equ    1    ; flag for segment decode check
  7. ok_off        equ    2    ; flag for offset decode check
  8. max_size    equ    4095    ; maximum size for SPY search region
  9. beep_delay    equ    4    ; number of clock ticks between beeps
  10. timer_count    equ    597    ; frequency of beep = 1,193,180 / timer_count
  11.  
  12. code        segment
  13.         assume cs:code, ds:code
  14.  
  15.         org    0
  16. key1        dw    ?    ; offset of int 20h instruction
  17.                 ;   used to verify a PSP location
  18.  
  19.         org    100h
  20.  
  21. begin:        jmp    start    ; jump to program start location
  22.  
  23. ;-------------------------------------------------------------------------------
  24. ; This copyright message appears when SPY.COM is "typed" to the screen.
  25. ;-------------------------------------------------------------------------------
  26.  
  27.         db    8,8,8,'   '
  28. copyright    db    rt,lf,'SPY Copyright (C) 1987 by Charles Lazo III, v1.0'
  29.         db    eof,8,' ',rt,lf,'$'
  30.  
  31. key2        dw    1234h    ; keys used to determine prior load of SPY
  32. key3        dw    5678h
  33.  
  34. oldint8             dd    ?    ; double word storage for old int 8 vector
  35. beeps        dw    0    ; number of beeps (notices) to send to user
  36. delay        dw    1    ; number of clock ticks 'til next beep
  37. beep_on        db    0    ; beep on/off status
  38. spy_size    dw    ?    ; number of bytes to spy on
  39. resident    db    0    ; indicates prior load of SPY (0 = none)
  40.  
  41. spy_location    label    dword
  42. spy_off        dw    ?    ; storage for value of offset for SPYing
  43. spy_seg        dw    ?    ; storage for value of segment for SPYing
  44.  
  45. ;-------------------------------------------------------------------------------
  46. ; Comparisons of the spied region and the spy buffer (set up initially as a copy
  47. ; of the spied region) are made in this addition to the timer interrupt.
  48. ; Changes to the spied region are counted and the spy buffer is updated.  The
  49. ; speaker is turned on and off here, but frequency is set during program
  50. ; initialization.
  51. ;-------------------------------------------------------------------------------
  52.  
  53. newint8        proc    near
  54.         push    ax        ; save interrupted program's registers
  55.         push    bx
  56.         push    cx
  57.         push    si
  58.         push    di
  59.         push    ds
  60.         push    es
  61.  
  62.         mov    ax,cs        ; our data lies here
  63.         mov    ds,ax
  64.  
  65.         lea    si,spy_buffer    ; point to our buffer
  66.         les    di,spy_location    ; point to spied region
  67.         mov    cx,spy_size    ; compare whole region
  68.         cld            ; forward!
  69. cmp_more:    repz    cmpsb        ; compare until no match or cx = 0
  70.         jz    cmp_done    ; if zero, then cx = 0 and we're done
  71.         inc    beeps        ; account for a change
  72.         mov    al,es:[di-1]    ; change accounted; update spy_buffer
  73.         mov    [si-1],al
  74.         or    cx,cx        ; set zero flag by cx (avoid inf loop)
  75.         jmp    short cmp_more    ; continue 'til done
  76.  
  77. cmp_done:    cmp    beep_on,0    ; is the beep on?
  78.         jz    do_beep?    ; no, shall we do a beep?
  79.         dec    beep_on        ; yes, turn it off
  80.         in    al,97        ; get speaker control bits
  81.         and    al,0fch        ; set them off
  82.         out    97,al        ; turn off speaker
  83.         jmp    short exit    ; job done; get out
  84. do_beep?:    cmp    beeps,0        ; are there beeps to be done?
  85.         jz    delay1        ; no, get out
  86.         dec    delay        ; reduce delay 'til next beep
  87.         jnz    exit        ; not zero, then exit
  88.         in    al,97        ; get speaker control bits
  89.         or    al,3        ; set them on
  90.         out    97,al        ; turn on speaker
  91.         inc    beep_on        ; signal beep is on
  92.         mov    delay,beep_delay; reinitialize delay counter
  93.         dec    beeps        ; one less beep to do
  94.         jmp    short exit    ; leave now
  95. delay1:        mov    delay,1        ; don't wait for first beep of a series
  96. exit:        pop    es        ; restore registers
  97.         pop    ds
  98.         pop    di
  99.         pop    si
  100.         pop    cx
  101.         pop    bx
  102.         pop    ax
  103.         jmp    dword ptr cs:oldint8    ; continue with interrupt
  104. newint8        endp
  105.  
  106. ;-------------------------------------------------------------------------------
  107. ; Here the region spied upon is copied to an area of the TSR that remains in
  108. ; memory after termination, the spy_buffer.  The es register is equal either to
  109. ; cs if SPY has not yet been loaded or to the value of cs when SPY was loaded
  110. ; previously (accomplished by a call to the set_es routine).
  111. ;-------------------------------------------------------------------------------
  112.  
  113. copy_spied:    lea    di,spy_buffer    ; destination of copy
  114.         mov    si,spy_off    ; the offset is source of copy
  115.         mov    cx,spy_size    ; number of bytes to copy
  116.         mov    ax,spy_seg    ; load segment of SPY region to ds
  117.         push    ds        ; SOD (save our data)
  118.         mov    ds,ax
  119.         cld            ; forward copy
  120.         rep    movsb        ; copy the SPY region to spy_buffer
  121.         pop    ds        ; RestoreOD
  122.  
  123.         cmp    resident,0    ; is SPY currently resident in memory?
  124.         je    tsr        ; no, make it so
  125.         mov    ax,4c00h    ; yes, end with error code 0
  126.         int    21h
  127.  
  128. ;-------------------------------------------------------------------------------
  129. ; SPY has not yet been loaded into memory, so we do it now.  First the 8253-5
  130. ; chip that generates the frequency of the beeps is initialized with the value
  131. ; given by the constant timer_count.  Then the new interrupt 8 routine is
  132. ; spliced in and finally the constant max_size is used to reserve enough memory
  133. ; for the largest permissible spy buffer.
  134. ;-------------------------------------------------------------------------------
  135.  
  136. tsr:        mov    delay,beep_delay; initialize delay counter
  137.  
  138.         ; set 8253-5 programmable timer to chosen frequency
  139.         mov    al,182        ; byte to initialize 8253 timer
  140.         out    67,al        ; tell timer next two bytes are count
  141.         mov    ax,timer_count    ; get timer count
  142.         out    66,al        ; output low byte
  143.         mov    al,ah
  144.         out    66,al        ; output high byte
  145.  
  146.         mov    ax,3508h    ; get the interrupt 8 (clock) vector
  147.         int    21h        ;   with DOS function 35h call
  148.  
  149. ; Retain offset and segment of interrupt 8 vector:
  150.  
  151.         mov    word ptr cs:oldint8,bx
  152.         mov    word ptr cs:oldint8+2,es
  153.  
  154.         lea    dx,newint8    ; place offset in dx
  155.         mov    ax,2508h    ; set its pointer into interrupt table
  156.         int    21h        ;   with DOS function 25h call
  157.  
  158.         lea    dx,spy_buffer    ; where SPY buffer begins
  159.         mov    cx,max_size    ; add the maximum size of the buffer:
  160.         add    dx,cx
  161.         mov    cl,4        ; compute number of paragraphs to save:
  162.         shr    dx,cl        ;   bytes to paragraphs in dx
  163.         inc    dx        ;   insure sufficient size for buffer
  164.         mov    ax,3100h    ; terminate but stay resident code = 0
  165.         int    21h
  166.  
  167. ;-------------------------------------------------------------------------------
  168. ; The following is initialization code and data that is overwritten by the data
  169. ; copied to the spy buffer when this buffer is initialized with a copy of the
  170. ; spied region.
  171. ;-------------------------------------------------------------------------------
  172.  
  173. spy_buffer:    ; this is where SPY will store a copy of the SPY region
  174.         ;   to later check for any changes to the region
  175.  
  176. syntax        db    rt,lf,'SPY syntax:  SPY xxxx:yyyy L zzz',rt,lf,rt,lf
  177.         db    'Where xxxx, and yyyy are hexadecimal numbers up to '
  178.         db    'four digits in length and',rt,lf
  179.         db    'zzz is a one to three digit hexadecimal number.  SPY '
  180.         db    'will monitor the segment-',rt,lf
  181.         db    'offset region xxxx:yyyy for a length of zzz bytes and '
  182.         db    'report to the user with a',rt,lf
  183.         db    'number of beeps equal to the number of bytes changed '
  184.         db    'in that region if and when',rt,lf
  185.         db    'any are changed.',rt,lf,'$'
  186.  
  187. progress    db    0    ; flags for progress of command line conversion
  188.  
  189. ;-------------------------------------------------------------------------------
  190. ; This routine will convert an ASCII hex digit in al (either upper or lower case
  191. ; alpha hex) into a 1-of-16 binary value in al.
  192. ;-------------------------------------------------------------------------------
  193.  
  194. make_binary    proc    near        ; hex ASCII digit in al to binary in al
  195.         cmp    al,'0'        ; less than "0", then not hex digit
  196.         jb    not_digit
  197.         cmp    al,'f'        ; greater than "f", then not hex digit
  198.         ja    not_digit
  199.         cmp    al,'9'        ; test for numeric digit
  200.         ja    not_numeric    ; not a numeric digit
  201.         sub    al,'0'        ; convert to binary
  202.         ret
  203. not_numeric:    cmp    al,'F'        ; over "F"?
  204.         ja    low_case    ; yes, test for lower case
  205.         cmp    al,'A'        ; less than "A"?
  206.         jb    not_digit    ; yes, not hex digit
  207.         sub    al,37h        ; convert to binary
  208.         ret
  209. low_case:    cmp    al,'a'        ; less than "a"?
  210.         jb    not_digit    ; yes, not hex digit
  211.         sub    al,57h        ; convert to binary
  212.         ret
  213. not_digit:    stc            ; set carry flag if not hex digit
  214.         ret
  215. make_binary    endp
  216.  
  217. ;-------------------------------------------------------------------------------
  218. ; This routine is called to allow the command line parse